package com.tobeing.picture.picker.customs;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;

import com.tobeing.picture.picker.models.Image;

import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * Created by Tobeing on 2017/11/15/015.
 * 图片加载
 */

public class ImageLoader {
    private static ImageLoader mInstance;
    private Context mContext;
    //缓存
    private LruCache<String, Bitmap> mLruCache;
    //线程池
    private ExecutorService mThreadPool;
    //默认后进先出
    private QueneType mQueneType = QueneType.LIFO;
    //任务队列
    private LinkedList<Runnable> mTaskQuene;
    //轮询线程池线程
    private Thread mThreadPoolThread;
    private Handler mThreadPoolHandler;
    //ui线程中的handler
    private Handler mUIHandler;
    private Semaphore mThreadPoolHandlerSemaphore = new Semaphore(0);
    private Semaphore mThreadPoolSemaphore;

    private int mWidth;
    private int mHeight;

    private ImageLoader(Context context, int threadCount, QueneType queneType) {
        init(context, threadCount, queneType);
    }

    /**
     * 初始化
     */
    private void init(Context context, int threadCount, QueneType queneType) {
        mContext = context;
        mThreadPoolThread = new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                mThreadPoolHandler = new Handler() {
                    @Override
                    public void handleMessage(Message msg) {
                        mThreadPool.execute(getTask());
                        try {
                            mThreadPoolSemaphore.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                };
                mThreadPoolHandlerSemaphore.release();
                Looper.loop();
            }
        };
        mThreadPoolThread.start();
        //获取最大使用内存
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        //缓存内存大小
        int cashMemory = maxMemory / 8;
        mLruCache = new LruCache<String, Bitmap>(cashMemory) {
            @Override
            protected int sizeOf(String url, Bitmap bitmap) {
                return bitmap.getRowBytes() * bitmap.getHeight();
            }
        };
        mThreadPool = Executors.newFixedThreadPool(threadCount);
        mTaskQuene = new LinkedList<Runnable>();
        mQueneType = queneType;
        mThreadPoolSemaphore = new Semaphore(threadCount);

        mWidth = mContext.getResources().getDisplayMetrics().widthPixels;
        mHeight = mContext.getResources().getDisplayMetrics().heightPixels;
    }

    /**
     * 单例模式
     *
     * @return
     */
    public static ImageLoader getInstance(Context context, int threadCount, QueneType queneType) {
        if (mInstance == null) {
            synchronized (ImageLoader.class) {
                if (mInstance == null) {
                    mInstance = new ImageLoader(context, threadCount, queneType);
                }
            }
        }
        return mInstance;
    }

    /**
     * 为imageview加载图片
     *
     * @param path
     * @param imageView
     */
    public void loadImage(final String path,final ImageView imageView) {
        imageView.setTag(path);
        if (mUIHandler == null) {
            mUIHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    Image image = (Image) msg.obj;
                    Bitmap bitmap = image.getBitmap();
                    ImageView iv = image.getImageView();
                    if(TextUtils.equals(image.getPath(), iv.getTag().toString())) {
                        iv.setImageBitmap(bitmap);
                    }
                }
            };
        }
        Bitmap bitmap = getBitmapFromLruCache(path);
        if (bitmap != null) {
            refreshImage(path, bitmap, imageView);
        } else {
            addTask(new Runnable() {
                @Override
                public void run() {
                    //压缩bitmap
                    Bitmap bitmap = decodeSampleBitmapFromPath(path);
                    addBitmapToLruCache(path, bitmap);
                    refreshImage(path, bitmap, imageView);
                    mThreadPoolSemaphore.release();
                }
            });
        }
    }

    private void refreshImage(String path, Bitmap bitmap, ImageView imageView) {
        Message message = Message.obtain();
        Image image = new Image();
        image.setPath(path);
        image.setBitmap(bitmap);
        image.setImageView(imageView);
        message.obj = image;
        mUIHandler.sendMessage(message);
    }

    /**
     * 将bitmapt加到缓存中
     *
     * @param path
     * @param bitmap
     */
    private void addBitmapToLruCache(String path, Bitmap bitmap) {
        if (getBitmapFromLruCache(path) == null) {
            if (bitmap != null) {
                mLruCache.put(path, bitmap);
            }
        }
    }

    /**
     * 从缓存获取bitmap
     *
     * @param path
     * @return
     */
    private Bitmap getBitmapFromLruCache(String path) {
        return mLruCache.get(path);
    }

    /**
     * 添加任务到任务队列
     *
     * @param runnable
     */
    private synchronized void addTask(Runnable runnable) {
        mTaskQuene.add(runnable);
        //避免线程并行mThreadPoolHandler没有初始化
        try {
            if (mThreadPoolHandler == null) {
                mThreadPoolHandlerSemaphore.acquire();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        mThreadPoolHandler.sendEmptyMessage(1001);
    }

    /**
     * 取出任务
     *
     * @return
     */
    private Runnable getTask() {
        if (mQueneType == QueneType.FIFO) {
            return mTaskQuene.removeFirst();
        } else if (mQueneType == QueneType.LIFO) {
            return mTaskQuene.removeLast();
        }
        return null;
    }

    /**
     * 压缩bitmap
     *
     * @param path
     * @return
     */
    private Bitmap decodeSampleBitmapFromPath(String path) {
        //获取图片宽高不加载图片
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        options.inSampleSize = caculateInSampleSize(options);
        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeFile(path, options);
        return bitmap;
    }

    private int caculateInSampleSize(BitmapFactory.Options options) {
        int outWidth = options.outWidth;
        int outHeight = options.outHeight;
        int inSampleSize = 1;
        if (outWidth > mWidth || outHeight > mHeight) {
            int widthRate = Math.round(outWidth * 1.0f / mWidth);
            int heightRate = Math.round(outHeight * 1.0f / mHeight);
            inSampleSize = Math.max(widthRate, heightRate);
        }
        return inSampleSize;
    }

    public void setSize(int width, int height) {
        mWidth = width;
        mHeight = height;
    }
}
